import { Select } from './select';
import { NBorder, NFill, NFont } from '../types/style.interface';
import { Config } from './config';
import { Inject, Injectable, InjectFactory, TFactory } from '../decorators/inject';
import { WatchValueChange } from '../utils/object-helper'
import { NExcel } from '../types';
import { Watch, Reference} from '../decorators/relation-value';
import { ICell } from '../types/z-excel.interface';
import { Transform, toJSON } from '../decorators/toJSON';
import { CellTypeManage } from './cell-type-manage';
import { FullControl } from './full-control';
import { ICellGroup, CellTypes, ICellEditor, ICellRender } from '../cell-types';
import { Value } from './value';
@Injectable()
@Transform()
export class Cell<T = any> implements ICell{
    public readonly position: {row: number, col: number} = {row: 0, col: 0};
    @toJSON(null)
    public fill: Partial<NFill.IFill> = null;
    @toJSON({})
    public border: Partial<NBorder.IBorder> = {};
    @toJSON({})
    public font: Partial<NFont.IFont> = {};
    @toJSON(null, {
        toCls: function(instance: Cell, value: any) {
            let val = instance.factory(Value);
            val.updateOriginValue(value);
            return val;
            // if(typeof value !== 'object') {
            //     value = {value: value};
            // }
            // let renderCls = instance.cellTypeManage.getRender(instance.type);
            // let renderInstance = instance.factory(renderCls);
            // renderInstance.init(value);
            // return renderInstance;
        },
        toObj: (val, instance: Cell) => {
            return instance.value.getOriginValue();
        }
    })
    public value: Value = null;

    @toJSON(null, {parsePriority: 10})
    public type: string|null = null;
    @toJSON(0, {
        toObj: (val, instance: Cell) => {
            if(val === instance.conf.header.row.height) {
                return undefined;
            } else {
                return val;
            }
        }
    })
    protected height: number = 0;
    @toJSON(false)
    public readonly heightChanged = false;
    @toJSON(0, {name: 'row'})
    protected _row: number = 0;
    @toJSON(0, {name: 'col'})
    protected _col: number = 0;
    protected typeForRenderEditor!: {type: string, render: ICellRender};
    constructor(
        protected conf: Config,
        // protected renderManage: CellRenderEditManage
        protected cellTypeManage: CellTypeManage,
        protected fullControll: FullControl,
        @InjectFactory() public factory: TFactory

    ) {
        this.height = this.conf.header.row.height;
    }
    public init() {
        // this.fill.background = null;
        // this.border = null;
        this.value = this.factory(Value);
    }
    /**
     * 计算cell所需要的实际高度
     */
    public calculateHeight(): number {
        return this.height;
    }
    public setHeight(h: number) {
        this.height = h;
        // @ts-ignore
        this.heightChanged = true;
    }
    public getLocation() {
        return {row: this._row, col: this._col};
    }
    public updateLocation(loc: {row?: number, col?: number}) {
        if(typeof loc.row === 'number') {
            this._row = loc.row;
        }
        if(typeof loc.col === 'number') {
            this._col = loc.col;
        }
    }
    public getRender() {
        let type: string;
        if(this.type === null) {
            type = this.fullControll.getCellType(this.position.row, this.position.col, null);
        } else {
            type = this.type;
        }
        if(!this.typeForRenderEditor || this.typeForRenderEditor.type !== type) {
            let info = this.cellTypeManage.getRender(type);
            let render = this.factory(info);
            render.cell = this;
            this.typeForRenderEditor = {type: type, render: render};
        }
        return this.typeForRenderEditor.render;
    }
    public updatePosition(row: number, col: number) {
        if(this.value) {
            this.value.updatePosition(row, col);
        }
        // @ts-ignore
        this.position = {row, col};
        this._row = row;
        this._col = col;
    }
}
